package n12_线程活跃性和锁粒度细分;

import lombok.extern.slf4j.Slf4j;
import utils.Sleeper;

import java.util.Random;

/**
 * @author fu
 * @date 2021-12-29 17:39
 * 概要：
 * ------------------------------------------------
 * |                                              |
 * |                哲学家就餐问题                  |
 * |                                              |
 * |===============================================
 *
 * 吃饭时要用两根筷子吃，桌上共有 5 根筷子，每位哲学家左右手边各有一根筷子。
 * 如果筷子被身边的人拿着，自己就得等待
 */
public class T3_zhexuejia_jiucan {

    public static void main(String[] args) {

        Chopstick c1 = new Chopstick("1");
        Chopstick c2 = new Chopstick("2");
        Chopstick c3 = new Chopstick("3");
        Chopstick c4 = new Chopstick("4");
        Chopstick c5 = new Chopstick("5");
        new Philosopher("苏格拉底--",   c1, c2).start();
        new Philosopher("柏拉图---",     c2, c3).start();
        new Philosopher("亚里士多德",  c3, c4).start();
        new Philosopher("赫拉克利特",  c4, c5).start();
        new Philosopher("阿基米德--",    c5, c1).start();

    }

}

// 哲学家类          [--- 继承了 Thread类 ---]
@Slf4j(topic = "c.P")
class Philosopher extends Thread {
    Chopstick left;
    Chopstick right;
    public Philosopher(String name, Chopstick left, Chopstick right) {
        super(name);
        this.left = left;
        this.right = right;
    }

    @Override
    public void run() {
        // 这里随机随眠 还能多走几步 不然只能 没人一只筷子 就死锁
        Sleeper.sleep(new Random().nextDouble());

        while (true) {
            // 获得左手筷子
            synchronized (left) {
                log.debug("--- 获得 左手筷子---");
                // 获得右手筷子
                synchronized (right) {
                    log.debug("+++ 获得 右手筷子+++");
                    // 吃饭
                    eat();
                }
                // 放下右手筷子
            }
            // 放下左手筷子
        }
    }

    Random random = new Random();
    private void eat() {
        log.debug("eating...");
        Sleeper.sleep(1);
//        Sleeper.sleep(random.nextInt(5));
    }
}


// 筷子类
class Chopstick {
    String name;
    public Chopstick(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "筷子{" + name + '}';
    }
}



